#include <stdlib.h>
#include <string.h> // memcpy()
#include <pthread.h>
#include "log/log.h"
#include "app_buffer.h"

static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;

Buffer *app_buffer_init(int size)
{
    // 动态分配buffer结构体内存
    Buffer *buffer = malloc(sizeof(Buffer));
    if (buffer == NULL)
    {
        log_warn("app_buffer_init malloc buffer failed");
        return NULL;
    }
    
    // 初始化ptr:动态分配内存
    buffer->ptr = malloc(size);
    if (buffer->ptr == NULL)
    {
        log_warn("app_buffer_init malloc buffer->ptr failed");
        free(buffer);
        return NULL;
    }
    
    // 初始化lock: 将初始化锁拷贝给lock
    memcpy(&buffer->lock, &init_lock, sizeof(pthread_mutex_t));

    // 初始化其它成员
    buffer->total_size = size;
    buffer->offset = 0;
    buffer->len = 0;

    log_debug("app_buffer_init success");

    // 返回buffer
    return buffer;
}

int app_buffer_free(Buffer *buffer)
{
    // 如果buffer为空，失败返回
    if (buffer == NULL)
    {
        log_warn("app_buffer_free buffer is NULL");
        return -1;
    }
    // 释放ptr
    free(buffer->ptr);
    // 释放buffer(lock会被同时释放)
    free(buffer);
}

int app_buffer_write(Buffer *buffer, unsigned char *data, int len)
{
    // 如果buffer或data为空，失败返回
    if (buffer == NULL || data == NULL)
    {
        log_warn("app_buffer_write buffer or data is NULL");
        return -1;
    }
    // 如果len小于等于0，失败返回
    if (len <= 0)
    {
        log_warn("app_buffer_write len is invalid");
        return -1;
    }
    // 如果要写的数据超过了剩余空间大小，失败返回
    if (len > buffer->total_size - buffer->len)
    {
        log_warn("app_buffer_write buffer is overflow fail");
        return -1;
    }

    // 准备操作buffer数据前加锁
    pthread_mutex_lock(&buffer->lock);

    // 计算出写数据开始的位置
    int write_start = buffer->offset + buffer->len;
    // 如果超过最大值(total_size-1)，修正一下
    if (write_start >buffer->total_size - 1)
    {
        write_start = write_start - buffer->total_size;
    }

    // 写数据
    // 判断是一次写入 还是二次写入 条件：如果一次连续写入的结束位置是否超过最大值
    if (write_start + len <= buffer->total_size-1)
    { // 情况1：一次连续写入
        memcpy(buffer->ptr + write_start, data, len);
    }
    else
    { // 情况2：二次写入
        // 计算出要写的第一段长度
        int len1 = buffer->total_size - write_start;
        // 写入第一段数据
        memcpy(buffer->ptr + write_start, data, len1);
        // 写入第二段数据
        memcpy(buffer->ptr, data + len1, len - len1);
    }

    // 更新 len
    buffer->len += len;

    // 操作buffer结束后解锁
    pthread_mutex_unlock(&buffer->lock);

    log_debug("app_buffer_write success, total_size=%d, len=%d, offset=%d", buffer->total_size, buffer->len, buffer->offset);

    return 0;
}

int app_buffer_read(Buffer *buffer, unsigned char *data, int len)
{
    // 如果buffer或data为空，失败返回
    if (buffer == NULL || data == NULL)
    {
        log_warn("app_buffer_read buffer or data is NULL");
        return -1;
    }
    // 如果len小于等于0，失败返回
    if (len <= 0)
    {
        log_warn("app_buffer_read len is invalid");
        return -1;
    }
    // 如果data容器长度大于缓存数据的len，修正为len
    if (len > buffer->len)
    {
        len = buffer->len;
    }

    // 判断是一次连续读取，还是二次连续读取
    if (buffer->offset + len <= buffer->total_size - 1)
    { // 情况1：一次连续读取
        memcpy(data, buffer->ptr + buffer->offset, len);
        // 更新offset
        buffer->offset += len;
    }
    else
    { // 情况2：二次连续读取
        // 计算出要读的第一段长度
        int len1 = buffer->total_size - buffer->offset;
        
        // 读取第一段数据
        memcpy(data, buffer->ptr + buffer->offset, len1);
        // 读取第二段数据
        memcpy(data + len1, buffer->ptr, len - len1);
        // 更新offset
        buffer->offset = len - len1;

        
    }

    // 更新len
    buffer->len -= len;

    log_debug("app_buffer_read success, read len=%d total_size=%d, len=%d, offset=%d", len, buffer->total_size, buffer->len, buffer->offset);

    // 返回读取的长度
    return len;
}